import os
import sys
import numpy as np
import requests
import json
import datetime
import yaml
from PIL import Image
import io
import base64
import random

import cv2
from enum import Enum
from . import logger

alert_time = [{}, {}, {}, {}]
yaml_data = None
pgie_classes_str = ["single", "double", "single screw", "double screw", "stain", "discard"]
distance = None


class Flaw(Enum):
    QSLM = "缺少螺母"
    MYTJYL = "螺母没有调节余量"
    DISCARD = "废孔未封堵"
    STAIN = "隧道壁渗水"


def get_info(n_frame, obj_meta, confidence):
    confidence = '{0:.2f}'.format(confidence)
    rect_params = obj_meta.rect_params
    top = int(rect_params.top)
    left = int(rect_params.left)
    width = int(rect_params.width)
    height = int(rect_params.height)
    obj_name = pgie_classes_str[obj_meta.class_id]
    # 打印结果的相关信息
    # print(f"confidence = {confidence},top = {top},left = {left}, name = {obj_name}")

    obj_info = {"obj_name": obj_name,
                "top": top,
                "left": left,
                "width": width,
                "height": height,
                "confidence": confidence}
    # logger.logger.info(obj_info)
    return obj_info


def is_flawed(obj_list, index, frame):
    now = datetime.datetime.now()
    global alert_time, distance
    global yaml_data
    # global distance
    flaw_set = set()
    # 将配置文件的地址读取，按index
    if not yaml_data:
        current_dir = os.path.dirname(os.path.abspath(__file__))
        yaml_path = os.path.join(current_dir, "../../conf/yolo.yaml")
        yaml_data = parse(yaml_path)
    alert_interval = yaml_data['interval']
    address = yaml_data['streams'][index]

    for obj in obj_list:
        if obj['obj_name'] == "single screw":
            flaw_set.add(Flaw.QSLM.value)
        elif obj['obj_name'] == "single":
            flaw_set.update([Flaw.QSLM.value, Flaw.MYTJYL.value])
        elif obj['obj_name'] == "double":
            flaw_set.add(Flaw.MYTJYL.value)
        elif obj['obj_name'] == "discard":
            flaw_set.add(Flaw.DISCARD.value)
        elif obj['obj_name'] == "stain":
            flaw_set.add(Flaw.STAIN.value)
        else:
            flaw_set.add(obj['obj_name'])
    # logger.logger.info(flaw_set)
    if "alert_time" not in alert_time[index] or (
            now - alert_time[index]["alert_time"]).total_seconds() > alert_interval:
        alert_time[index]['alert_time'] = now

        # 获取小车的距离 http://127.0.0.1:10000/getDistance
        try:
            json = {
                'uuid': yaml_data['uuid'],
                'timeDate': now.strftime("%Y-%m-%d %H:%M:%S")
            }
            response = requests.post("http://127.0.0.1:10000/getDistance", json=json, timeout=5.0)
        except Exception:
            logger.logger.error("请求小车距离失败")
        position = None
        try:
            res = response.json()
            if res['result'] == 0:
                position = res['value']
        except Exception:
            logger.logger.error("小车的响应异常")
        # logger.logger.info(f"{flaw_set}, {address}")
        if position is not None and (distance is None or distance != position):
            logger.logger.info("开始报警")
            distance = position

            alert(list(flaw_set), now, address, frame, position)
        else:
            logger.logger.info(f"小车已停止在{position}位置处")
            # alert(list(flaw_set), now, address, frame, position)


def test_is_flawed(index, frame):
    now = datetime.datetime.now()
    global alert_time
    global yaml_data
    flaw_set = set()
    
    # 将配置文件的地址读取，按index
    if not yaml_data:
        current_dir = os.path.dirname(os.path.abspath(__file__))
        yaml_path = os.path.join(current_dir, "../../conf/yolo.yaml")
        yaml_data = parse(yaml_path)
    alert_interval = yaml_data['interval']
    
    address = yaml_data['streams'][int(index)]


    # 随机生成1到4的缺陷
    random_count = random.randint(1, 4)
    flaw_list = ["缺少螺母", "螺母没有调节余量", "废孔未封堵", "隧道壁渗水"]
    flaw_set.update(random.sample(flaw_list, random_count))

    # logger.logger.info(flaw_set)
    if "alert_time" not in alert_time[index] or (
            now - alert_time[index]["alert_time"]).total_seconds() > alert_interval:
        alert_time[index]['alert_time'] = now

        # 随机生成距离
        position = round(random.uniform(1, 100), 2)

        logger.logger.info("测试报警")

        alert(list(flaw_set), now, address, frame, position)


def alert(alert_type, json_time, address, image, position):
    # 格式化时间为 "YYYY-MM-DD hh:mm:ss" 的形式
    format_time = json_time.strftime("%Y-%m-%d %H:%M:%S")

    # print(alert_json)
    logger.logger.info(f'type={alert_type}, time={format_time}, address={address}, position={position}')
    url = yaml_data['alert_endpoint']  # 替换为接收报警的 IP 接口地址
    type = alert_type
    time = format_time
    headers = {
        "Content-Type": "multipart/form-data",  # 设置Content-Type为multipart/form-data
    }
    retval, image_bytes = cv2.imencode('.jpg', image)
    files = {'image': ('image.jpg', image_bytes, 'image/jpeg')}
    data = {'time': time, 'type': type, 'address': address}
    data = []
    for item in type:
        data.append({
            'flawType': item,
            'flawName': item,
            'flawDesc': "",
            'flawDistance': position,
            'flawRTSP': address
        })
    files = {'file': ("alert.jpg", image_bytes, "multipart/form-data"),
             'data': (None, json.dumps(data), "application/json")}

    try:
        response = requests.post(url, files=files, timeout=5.0)
        if response.status_code == 200:
            logger.logger.info("报警成功！")
            logger.logger.info(f"报警内容：{data}")
        else:
            logger.logger.error(f"报警失败，状态码：{response.status_code}, 报警内容：{data}")
    except requests.exceptions.RequestException as e:
        logger.logger.error(f"报警请求出错：{e}")


def array2base64(image):
    # 将ndarray转换为PIL图像对象
    image_pil = Image.fromarray(image)

    # 保存图像为字节流
    image_bytesio = io.BytesIO()
    image_pil.save(image_bytesio, format='PNG')

    # 将字节流转换为Base64字符串
    image_base64 = base64.b64encode(image_bytesio.getvalue()).decode('utf-8')
    return image_base64


def draw_bounding_boxes(image, obj_meta, confidence):
    confidence = '{0:.2f}'.format(confidence)
    rect_params = obj_meta.rect_params
    top = int(rect_params.top)
    left = int(rect_params.left)
    width = int(rect_params.width)
    height = int(rect_params.height)
    obj_name = pgie_classes_str[obj_meta.class_id]
    # image = cv2.rectangle(image, (left, top), (left + width, top + height), (0, 0, 255, 0), 2, cv2.LINE_4)
    color = (0, 0, 255, 0)
    w_percents = int(width * 0.05) if width > 100 else int(width * 0.1)
    h_percents = int(height * 0.05) if height > 100 else int(height * 0.1)
    linetop_c1 = (left + w_percents, top)
    linetop_c2 = (left + width - w_percents, top)
    image = cv2.line(image, linetop_c1, linetop_c2, color, 6)
    linebot_c1 = (left + w_percents, top + height)
    linebot_c2 = (left + width - w_percents, top + height)
    image = cv2.line(image, linebot_c1, linebot_c2, color, 6)
    lineleft_c1 = (left, top + h_percents)
    lineleft_c2 = (left, top + height - h_percents)
    image = cv2.line(image, lineleft_c1, lineleft_c2, color, 6)
    lineright_c1 = (left + width, top + h_percents)
    lineright_c2 = (left + width, top + height - h_percents)
    image = cv2.line(image, lineright_c1, lineright_c2, color, 6)
    # Note that on some systems cv2.putText erroneously draws horizontal lines across the image
    image = cv2.putText(image, obj_name + ',C=' + str(confidence), (left - 10, top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                        (0, 0, 255, 0), 2)
    return image


def parse(yaml_path):
    # 读取YAML文件
    with open(yaml_path, 'r') as file:
        data = yaml.safe_load(file)

    # 将字符串"True"转换为布尔值True
    data['no_display'] = data['no_display']
    data['file_loop'] = data['file_loop']
    data['disable_probe'] = data['disable_probe']
    data['silent'] = data['silent']
    logger.logger.info(data)

    return data



if __name__ == '__main__':
    pass
